<?php

class Money {
	public $amount;
	public $currency;
	
	function __construct( $amount, $currency ) {
		$this->amount = "" . $amount;
		$this->currency = $currency;
	}
}

class TransactionInfo {
	public $transactionID;
	public $transactionStatus;
	public $externalID;
	public $redirectURL;
}

class ErrorResponse extends Exception {
	/**
	 * The error reason. One of the following values:
	 * <ul>
	 *   <li>MalformedRequest</li>
	 *   <li>InvalidRequest</li>
	 *   <li>AuthenticationFailed</li>
	 *   <li>TechnicalError</li>
	 * </ul>
	 */
	public $name;
	/**
	 * Details of the error. One of the following values:
	 * <ul>
	 *   <li>MalformedRequest</li>
	 *   <li>EmptyRequest</li>
	 *   <li>UnknownRequest</li>
	 *   <li>InvalidRequest</li>
	 *   <li>InvalidAPIConfigurationID</li>
	 *   <li>APIConfigurationNotActive</li>
	 *   <li>APIConfigurationLocked</li>
	 *   <li>DuplicateExternalID</li>
	 *   <li>LimitsExceeded</li>
	 *   <li>TransactionNotFound</li>
	 *   <li>TransactionNotCancellable</li>
	 *   <li>AuthenticationFailed</li>
	 *   <li>InvalidSignature</li>
	 *   <li>TechnicalError</li>
	 * </ul>
	 */
	public $detail; 
	/** A string with a human readable description about what went wront with the request. */
	public $description;
		
	function __construct( $soapFault) {
		$this->name =  $soapFault->detail->Error_Response->name;
		$this->detail =  $soapFault->detail->Error_Response->detail;
		$this->description =  $soapFault->detail->Error_Response->description;
	}
}

abstract class AbstractRequest {
	const SALT_SIZE = 8;

	protected $apiConfigurationID;
	protected $requesterSignature;
	
	private $requestName;

	protected function __construct( $apiConfigurationID, $requestName ) {
		$this->apiConfigurationID = $apiConfigurationID;
		$this->requestName = $requestName;
	}
		
	protected function createSalt() {
		for( $i = 0; $i < self::SALT_SIZE; $i++ ) {
			$salt[] = sprintf( "%02X", rand( 0, 255 ) );
		}
		return implode( $salt );
	}

	protected function createSignature( $secretKey, $arguments ) {
		$salt = $this->createSalt();
		$concatenated = $this->apiConfigurationID . "#" . $this->requestName . "#"
						. implode( "#", $arguments )
						. "#" . $secretKey . "#" . $salt;
		$sha1 = strtoupper( sha1( $concatenated ) );
		$signature = $salt . "#" . $sha1;
		return $signature;
	}
	

}

class CreateTransactionRequest extends AbstractRequest {
	private $amount;
	private $title;
	private $description;
	private $buyerFbUserID;
	private $returnURL;
	private $externalID;
	
	function __construct( $apiConfigurationID, $amount, $title, $description, $buyerFbUserID, $returnURL, $externalID, $secretKey ) {
		parent::__construct( $apiConfigurationID, "CreateTransaction_Request" );
		$this->amount = $amount;
		$this->title = $title;
		$this->description = $description;
		$this->buyerFbUserID = $buyerFbUserID;
		$this->returnURL = $returnURL;
		$this->externalID = $externalID;
		$this->requesterSignature = $this->createSignature( $secretKey, array( $buyerFbUserID, $amount->amount, $amount->currency ) );
	}
}

class CreateTransactionResponse extends TransactionInfo {
}

class GetTransactionStatusRequest extends AbstractRequest {
	private $transactionID;
	private $externalID;

	function __construct( $apiConfigurationID, $transactionOrExternalID, $isExternalID, $secretKey ) {
		parent::__construct( $apiConfigurationID, "GetTransactionStatus_Request" );
		if( $isExternalID ) {
			$this->externalID = $transactionOrExternalID;
		} else {
			$this->transactionID = $transactionOrExternalID;
		}
		$this->requesterSignature = $this->createSignature( $secretKey, array( $transactionOrExternalID ) );
	}
}

class GetTransactionStatusResponse extends TransactionInfo {
}

class CancelTransactionRequest extends AbstractRequest {
	private $transactionID;
	
	function __construct( $apiConfigurationID, $transactionID, $secretKey ) {
		parent::__construct( $apiConfigurationID, "CancelTransaction_Request" );
		$this->transactionID = $transactionID;
		$this->requesterSignature = $this->createSignature( $secretKey, array( $transactionID ) );
	}
}

class CancelTransactionResponse extends TransactionInfo {
}

?>
